#include <stdio.h>
#include <stdlib.h>
#include "abcrypto.h"

#include "hash.h"
#include "cipher.h"

static struct abcrypto_skcipher *get_skcipher(uint16_t alg)
{
	switch (alg) {
	case ABCRYPTO_CIPHER_AES_128_ECB:
	case ABCRYPTO_CIPHER_AES_128_CBC:
	case ABCRYPTO_CIPHER_AES_128_CTR:
	case ABCRYPTO_CIPHER_AES_128_CFB:
	case ABCRYPTO_CIPHER_AES_128_OFB:
	case ABCRYPTO_CIPHER_AES_192_ECB:
	case ABCRYPTO_CIPHER_AES_192_CBC:
	case ABCRYPTO_CIPHER_AES_192_CTR:
	case ABCRYPTO_CIPHER_AES_192_CFB:
	case ABCRYPTO_CIPHER_AES_192_OFB:
	case ABCRYPTO_CIPHER_AES_256_ECB:
	case ABCRYPTO_CIPHER_AES_256_CBC:
	case ABCRYPTO_CIPHER_AES_256_CTR:
	case ABCRYPTO_CIPHER_AES_256_CFB:
	case ABCRYPTO_CIPHER_AES_256_OFB:
	case ABCRYPTO_CIPHER_SM4_ECB:
	case ABCRYPTO_CIPHER_SM4_CBC:
	case ABCRYPTO_CIPHER_SM4_CTR:
	case ABCRYPTO_CIPHER_SM4_CFB:
	case ABCRYPTO_CIPHER_SM4_OFB:
		return openssl_cipher();
	default:
		return NULL;
	}
}

static struct abcrypto_auth *get_auth(uint16_t alg)
{
	// printf("%#x %#x %#x\n", (alg & 0xff00), (alg & 0xf0), (alg & 0xf));
	if ((alg & 0xff00) == 0x0100) {
		if ((alg & 0xf0) == 0x00) {
			switch ((alg & 0xf)) {
			case ABCRYPTO_AUTH_ALG_MD5:
			case ABCRYPTO_AUTH_ALG_SHA1:
			case ABCRYPTO_AUTH_ALG_SHA224:
			case ABCRYPTO_AUTH_ALG_SHA256:
			case ABCRYPTO_AUTH_ALG_SHA384:
			case ABCRYPTO_AUTH_ALG_SHA512:
			case ABCRYPTO_AUTH_ALG_SHA3_224:
			case ABCRYPTO_AUTH_ALG_SHA3_256:
			case ABCRYPTO_AUTH_ALG_SHA3_384:
			case ABCRYPTO_AUTH_ALG_SHA3_512:
			case ABCRYPTO_AUTH_ALG_SM3:
				/* hash*/
				return openssl_hash();
			default:
				break;
			}

		} else if ((alg & 0xf0) == 0x10) {
			switch ((alg & 0xf)) {
			case ABCRYPTO_AUTH_ALG_MD5:
			case ABCRYPTO_AUTH_ALG_SHA1:
			case ABCRYPTO_AUTH_ALG_SHA224:
			case ABCRYPTO_AUTH_ALG_SHA256:
			case ABCRYPTO_AUTH_ALG_SHA384:
			case ABCRYPTO_AUTH_ALG_SHA512:
			case ABCRYPTO_AUTH_ALG_SHA3_224:
			case ABCRYPTO_AUTH_ALG_SHA3_256:
			case ABCRYPTO_AUTH_ALG_SHA3_384:
			case ABCRYPTO_AUTH_ALG_SHA3_512:
			case ABCRYPTO_AUTH_ALG_SM3:
				/* hash*/
				return openssl_hmac();
			default:
				break;
			}
		}
	}

	return NULL;
}

static struct abcrypto_instance openssl = { .name = "openssl",
					    .get_skcipher = get_skcipher,
					    .get_auth = get_auth };

/*范围是 0 到 100，数值越小，函数执行的优先级越高*/
static __attribute__((constructor(200))) void _register_openssl(void)
{
	/* register cipher first */
	/* register auth first */

	int ret = register_instance(&openssl);
	if (ret) {
		fprintf(stderr, "fill openssl failed\r\n");
	} else {
		fprintf(stdout, "fill openssl ok\r\n");
	}
}
